package com.ssl.order.service;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ssl.common.response.CommonResponse;
import com.ssl.common.response.ResponseCode;
import com.ssl.common.response.ResponseUtils;
import com.ssl.order.constant.ConstantUtils;
import com.ssl.order.fegin.WareServiceClient;
import com.ssl.order.pay.facade.PayFacade;
import com.ssl.order.pojo.*;
import com.ssl.order.utils.Constants;
import com.ssl.order.utils.IDWorker;
import com.ssl.order.utils.RedisCommonProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单实现类
 */
@Service
public class OrderService {
    @Autowired
    private RedisCommonProcessor redisCommonProcessor;

    @Autowired
    private WareServiceClient wareServiceClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PayFacade payFacade;

    public OrderPageResponse createOrderPage(List<OderPageRequest> oderPageRequests, String personId) {
        //生成 提交订单时 所需要的 唯一的 pageToken. 并且存储到后端的 redis 服务器中
        String pageToken = UUID.randomUUID().toString();
        redisCommonProcessor.set(personId + pageToken, pageToken, 300);

        //运费计算, 需要访一个新的 微服务： 仓库微服务
        Integer freight = wareServiceClient.calculateFreight(oderPageRequests);

        //总价计算
        BigDecimal totalPrice = new BigDecimal(0);
        for (OderPageRequest oderPageRequest : oderPageRequests) {
            totalPrice = totalPrice.add(oderPageRequest.getPrice().multiply(new BigDecimal(oderPageRequest.getCount())));
        }
        totalPrice = totalPrice.add(new BigDecimal(freight));

        return OrderPageResponse.builder()
                .pageToken(pageToken)
                .freight(freight)
                .totalPrice(totalPrice)
                .build();
    }

    public CommonResponse submitOrder(OrderSubmitRequest orderSubmitRequest) {
        // 验证 pageToken保证原子性
        String personId = orderSubmitRequest.getPersonId();
        String pageToken = orderSubmitRequest.getPageToken();
//        String cachedToken = (String) redisCommonProcessor.get(personId + pageToken);
//        if(cachedToken == null || !cachedToken.equals(pageToken)) {
//            return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), null, "your pageToken is expired or it's repeat!")
//        }
//        redisCommonProcessor.remove(personId + pageToken);
        String luaScripts = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Long validate = redisCommonProcessor.runLuaScripts(luaScripts, pageToken, personId + pageToken);
        if(validate == 0) {
            return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), null, "your pageToken is expired or it's repeat!");
        }

        // 订单号（全局唯一的）
        IDWorker idWorker = new IDWorker(10, 11);
        String orderId = String.valueOf(idWorker.nextId());
        orderSubmitRequest.setOrderId(orderId);

        // 验证并锁定库存
        //如果有一个商品或多个商品没有存货，订单不生成，提示用户，返回给前端库存不足的商品信息
        List<OrderWareLockResponse> orderWareLockResponses = wareServiceClient.lockWare(orderSubmitRequest);
        Map<Boolean, List<OrderWareLockResponse>> wareLockMap =
                orderWareLockResponses.stream().collect(Collectors.groupingBy(OrderWareLockResponse::isLocked));
        if(wareLockMap.get(false) != null) {
            return ResponseUtils.failResponse(ResponseCode.BAD_REQUEST.getCode(), orderWareLockResponses, "your pageToken is expired or it's repeat!");
        }

        // 存入redis，用来进行我们下一步支付时的查询，减少DB依赖
        createOrderInfo(orderSubmitRequest);
        redisCommonProcessor.set(orderId, orderSubmitRequest, 1200);
        // 发送到 待支付 queue中（15min过期queue）
        rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE, ConstantUtils.ORDER_CONFIRM_QUEUE, orderSubmitRequest);

        // 发送到 订单 queue中。（异步的订单数据保存）
        rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE, ConstantUtils.ORDER_DATA_QUEUE, orderSubmitRequest);
        return ResponseUtils.okResponse(orderSubmitRequest);
    }
    private void createOrderInfo(OrderSubmitRequest orderSubmitRequest) {
        String orderStatus = OrderStatus.WAITING_PAY.name();
        Date createDate = new Date();
        orderSubmitRequest.setOrderStatus(orderStatus);
        orderSubmitRequest.setCreateTime(createDate);
    }

    public CommonResponse cancelOrder(String orderId) {
        Boolean released = wareServiceClient.releaseWare(orderId);
        if(released) {
            OrderSubmitRequest order = (OrderSubmitRequest) redisCommonProcessor.get(orderId);
            order.setOrderStatus(OrderStatus.ORDER_CANCELED.name());
            rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE, ConstantUtils.ORDER_DATA_QUEUE, order);
            return ResponseUtils.okResponse(true);
        }
        return ResponseUtils.okResponse(false);
    }

    public CommonResponse payOrder(String orderId, Integer payType) {
        OrderSubmitRequest order = (OrderSubmitRequest) redisCommonProcessor.get(orderId);
        if(order == null || !order.getOrderStatus().equals(OrderStatus.WAITING_PAY.name())) {
            //如果order 为null，需要去DB验证。
            throw new UnsupportedOperationException("订单异常！");
        }
        return ResponseUtils.okResponse(payFacade.pay(order, payType));
    }

    public CommonResponse alipaycallback(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
        //回调信息组装，用来验证我们的回调信息是正确的回调
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();

        for(Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for(int i = 0; i < values.length; i++) {
                valueStr = (i==values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            params.put(name, valueStr);
        }

        //验证签名
        boolean signed = AlipaySignature.rsaCheckV1(params, Constants.ALIPAY_PUBLIC_KEY, "UTF-8", Constants.SIGN_TYPE);
        if(signed) {
            //获取信息，发给财务，项目不写财务模块，此处省略这部分代码
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//            float total_amount = Float.parseFloat(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));

            //修改订单状态，并发送到订单queue
            OrderSubmitRequest order = (OrderSubmitRequest) redisCommonProcessor.get(out_trade_no);
            if(order == null || !order.getOrderStatus().equals(OrderStatus.WAITING_PAY.name())) {
                //如果order 为null，需要去DB验证。
                throw new UnsupportedOperationException("订单异常！");
            }
            order.setOrderStatus(OrderStatus.WAITING_SEND.name());
            rabbitTemplate.convertAndSend(ConstantUtils.ORDER_EXCHANGE, ConstantUtils.ORDER_DATA_QUEUE, order);

            //调用wareservice，将ware lock info的状态更新为 4
            // 小伙伴们自行添加下
        } else {
            throw new UnsupportedEncodingException("pay call back err!");
        }
        return null; //商户页面的跳转，跳转到我们的已经支付完成的页面。
    }
}
